package com.why.simpleboot.core.common.utils;


import org.reflections.Reflections;
import org.reflections.scanners.SubTypesScanner;
import org.reflections.scanners.TypeAnnotationsScanner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.annotation.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

/**
 * @program: why-simpleboot-framework
 * @description:
 * @author: @why
 * @create: 2021-05-22 17:17
 **/
public class SimpleReflectUtils {

    private static final Logger log = LoggerFactory.getLogger(SimpleReflectUtils.class);


    /**
     * 根据注解获取类
     *
     * @param basePackages:包地址
     * @return
     */
    public static Set<Class<?>> getClassesByAnnotation( Class<? extends Annotation> annotation, String... basePackages) {
        Reflections reflections = new Reflections(basePackages, new TypeAnnotationsScanner());

        Set<Class<?>> classSet = reflections.getTypesAnnotatedWith(annotation, true);

        return classSet;
    }


    /**
     * 反射执行目标方法
     *
     * @param method
     * @param args
     * @return
     */
    @Deprecated
    public static Object invokeMethod(Method method, Object... args) {
        Class<?> declaringClass = method.getDeclaringClass();

        try {
            Object target = declaringClass.newInstance();
            return method.invoke(target, args);

        } catch (IllegalAccessException | InvocationTargetException | InstantiationException e) {
            log.error("反射执行方法失败，method{},args{}", method, args, e);
        }
        return null;
    }


    /**
     * @param target
     * @return
     */
    public static Object getInstance(Class<?> target) {
        try {
            Object instance = target.newInstance();
            return instance;
        } catch (InstantiationException | IllegalAccessException e) {
            log.error("实例化对象失败~", e);
        }
        return null;
    }

    /**
     * 得到接口的实现类
     *
     * @param interfaceClass
     * @param basePackages
     * @return
     */

    /**
     * 这里在没有扫描答对应类型的实现类的时候 会抛出异常  : Scanner SubTypesScanner was not configured
     *
     * @param interfaceClass
     * @param basePackages
     * @param <T>
     * @return
     */
    public static <T> Set<Class<? extends T>> getSubclass(Class<T> interfaceClass,  String... basePackages) {
        try {
            Reflections reflections = new Reflections(basePackages, new SubTypesScanner());
            return reflections.getSubTypesOf(interfaceClass);

        } catch (Exception e) {
            log.warn("反射这没扫到东西，抛出个异常,捕获了,不慌");
            return new HashSet<>();
        }

    }

    /**
     * 完成为目标类的赋值操作
     *
     * @param target
     * @param field
     * @param filedInstance
     */
    public static void setFieldForTargetObject(Object target, Field field, Object filedInstance) {
        field.setAccessible(true);
        try {
            field.set(target, filedInstance);
        } catch (IllegalAccessException e) {
            log.error("为目标类设置属性失败。。。", e);
        }
    }

    /**
     * 反射执行目标方法
     *
     * @param method
     * @param args
     * @return
     */

    public static Object invokeMethod(Object target, Method method, Object... args) {
        try {
            return method.invoke(target, args);

        } catch (IllegalAccessException | InvocationTargetException e) {
            log.error("反射执行方法失败，method{},args{}", method, args, e);
            throw new RuntimeException(e);
        }
        //return null;
    }

    /**
     * 看看该类是否为接口的实现类
     *
     * @param
     * @param targetClass
     * @return
     */
    public static boolean isSubClass(Class<?> interfaceClass, Class<?> targetClass) {
        return interfaceClass.isAssignableFrom(targetClass);

    }


    public static void invokeMethodNoResult(Object target, Method method, Object... args) {
        try {
            method.invoke(target, args);
        } catch (IllegalAccessException | InvocationTargetException e) {
            log.error("反射执行方法失败，method{},args{}", method, args, e);
        }
    }


    /**
     * 递归获取指定注解上的注解
     *
     * @param srcAnnotation
     * @param target
     * @return
     */
    public static Annotation getTargetAnnotation(Class<? extends Annotation> srcAnnotation, Class<? extends Annotation> target) {
        if (srcAnnotation == Target.class || srcAnnotation == Retention.class || srcAnnotation == Documented.class) {
            return null;
        }
        Annotation result = null;
        for (Annotation annotation : srcAnnotation.getAnnotations()) {
            if (annotation.annotationType() != target) {
                result = getTargetAnnotation(annotation.annotationType(), target);
            } else {
                return annotation;
            }
        }
        return result;

    }


}
